{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Get Data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "import matplotlib.pyplot as plt\n",
    "import fitbit\n",
    "\n",
    "# gather_keys_oauth2.py file needs to be in the same directory. \n",
    "# also needs to install cherrypy: https://pypi.org/project/CherryPy/\n",
    "# pip install CherryPy\n",
    "import gather_keys_oauth2 as Oauth2\n",
    "import pandas as pd \n",
    "import datetime\n",
    "\n",
    "\n",
    "# YOU NEED TO PUT IN YOUR OWN CLIENT_ID AND CLIENT_SECRET\n",
    "CLIENT_ID=''\n",
    "CLIENT_SECRET=''"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## API Authorization"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "server=Oauth2.OAuth2Server(CLIENT_ID, CLIENT_SECRET)\n",
    "server.browser_authorize()\n",
    "ACCESS_TOKEN=str(server.fitbit.client.session.token['access_token'])\n",
    "REFRESH_TOKEN=str(server.fitbit.client.session.token['refresh_token'])\n",
    "auth2_client=fitbit.Fitbit(CLIENT_ID,CLIENT_SECRET,oauth2=True,access_token=ACCESS_TOKEN,refresh_token=REFRESH_TOKEN)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 5a.) Get One day of Data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# You will have to modify this \n",
    "# depending on when you started to use a fitbit\n",
    "oneDate = pd.datetime(year = 2019, month = 12, day = 10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "help(auth2_client.intraday_time_series)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "oneDayData = auth2_client.intraday_time_series('activities/heart',\n",
    "                                               base_date=oneDate,\n",
    "                                               detail_level='1sec')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "oneDayData"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df = pd.DataFrame(oneDayData['activities-heart-intraday']['dataset'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Look at the first 5 rows of the pandas DataFrame\n",
    "df.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# The first part gets a date in a string format of YYYY-MM-DD\n",
    "filename = oneDayData['activities-heart'][0]['dateTime'] +'_intradata'\n",
    "\n",
    "# Export file to csv\n",
    "df.to_csv(filename + '.csv', index = False)\n",
    "df.to_excel(filename + '.xlsx', index = False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## ## 5b.) Get Multiple Days of Data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# startTime is first date of data that I want. \n",
    "# You will need to modify for the date you want your data to start\n",
    "startTime = pd.datetime(year = 2019, month = 11, day = 27)\n",
    "endTime = pd.datetime.today().date() - datetime.timedelta(days=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "date_list = []\n",
    "df_list = []\n",
    "allDates = pd.date_range(start=startTime, end = endTime)\n",
    "\n",
    "for oneDate in allDates:\n",
    "    \n",
    "    oneDate = oneDate.date().strftime(\"%Y-%m-%d\")\n",
    "    \n",
    "    oneDayData = auth2_client.intraday_time_series('activities/heart', base_date=oneDate, detail_level='1sec')\n",
    "\n",
    "    df = pd.DataFrame(oneDayData['activities-heart-intraday']['dataset'])\n",
    "    \n",
    "    date_list.append(oneDate)\n",
    "    \n",
    "    df_list.append(df)\n",
    "    \n",
    "final_df_list = []\n",
    "\n",
    "for date, df in zip(date_list, df_list):\n",
    "\n",
    "    if len(df) == 0:\n",
    "        continue\n",
    "    \n",
    "    df.loc[:, 'date'] = pd.to_datetime(date)\n",
    "    \n",
    "    final_df_list.append(df)\n",
    "\n",
    "final_df = pd.concat(final_df_list, axis = 0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "## Optional Making of the data have more detailed timestamp (day and hour instead of day)\n",
    "hoursDelta = pd.to_datetime(final_df.loc[:, 'time']).dt.hour.apply(lambda x: datetime.timedelta(hours = x))\n",
    "minutesDelta = pd.to_datetime(final_df.loc[:, 'time']).dt.minute.apply(lambda x: datetime.timedelta(minutes = x))\n",
    "secondsDelta = pd.to_datetime(final_df.loc[:, 'time']).dt.second.apply(lambda x: datetime.timedelta(seconds = x))\n",
    "\n",
    "# Getting the date to also have the time of the day\n",
    "final_df['date'] = final_df['date'] + hoursDelta + minutesDelta + secondsDelta"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "final_df.tail()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "filename = 'all_intradata'\n",
    "final_df.to_csv(filename + '.csv', index = False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 6.) Try to Graph Intraday Data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# this is bad as time is duplicated over many days fixing the date column will fix the problem\n",
    "final_df.plot('time', 'value')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# The code below is not efficient as I call to_datetime twice\n",
    "hoursDelta = pd.to_datetime(final_df.loc[:, 'time']).dt.hour.apply(lambda x: datetime.timedelta(hours = x))\n",
    "minutesDelta = pd.to_datetime(final_df.loc[:, 'time']).dt.minute.apply(lambda x: datetime.timedelta(minutes = x))\n",
    "secondsDelta = pd.to_datetime(final_df.loc[:, 'time']).dt.second.apply(lambda x: datetime.timedelta(seconds = x))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Getting the date to also have the time of the day\n",
    "final_df['date'] = final_df['date'] + hoursDelta + minutesDelta + secondsDelta"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#final_df['temp_value'] = final_df['value'] + random.randint(-2, 2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# this fixed the problem.\n",
    "final_df.plot('date', 'value')\n",
    "plt.legend('')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "## Looking at a couple days only. \n",
    "startDate = pd.datetime(year = 2019, month = 12, day = 24)\n",
    "lastDate = pd.datetime(year = 2019, month = 12, day = 27)\n",
    "\n",
    "coupledays_df = final_df.loc[final_df.loc[:, 'date'].between(startDate, lastDate), :]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "coupledays_df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Just checking the number of the rows \n",
    "coupledays_df.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "coupledays_df.plot('date', 'value')\n",
    "plt.legend('')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fig, ax = plt.subplots(figsize=(10, 7))\n",
    "\n",
    "# Taken from: https://stackoverflow.com/questions/16266019/python-pandas-group-datetime-column-into-hour-and-minute-aggregations\n",
    "times = pd.to_datetime(coupledays_df['date'])\n",
    "coupledays_df.groupby([times.dt.date,times.dt.hour]).value.mean().plot(ax = ax)\n",
    "\n",
    "ax.grid(True,\n",
    "    axis = 'both',\n",
    "    zorder = 0,\n",
    "    linestyle = ':',\n",
    "    color = 'k')\n",
    "ax.tick_params(axis = 'both', rotation = 45, labelsize = 20)\n",
    "ax.set_xlabel('Date, Hour', fontsize = 24)\n",
    "ax.set_ylabel('Heart Rate', fontsize = 24)\n",
    "fig.tight_layout()\n",
    "fig.savefig('coupledaysavergedByMin.png', format = 'png', dpi = 300)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 7.) Resting Heart Rate"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# startTime is first date of data that I want. \n",
    "# You will need to modify for the date you want your data to start\n",
    "startTime = pd.datetime(year = 2020, month = 1, day = 1)\n",
    "endTime = pd.datetime.today().date() - datetime.timedelta(days=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "date_list = []\n",
    "resting_list = []\n",
    "\n",
    "allDates = pd.date_range(start=startTime, end = endTime)\n",
    "\n",
    "for oneDate in allDates:\n",
    "    \n",
    "    oneDate = oneDate.date().strftime(\"%Y-%m-%d\")\n",
    "    \n",
    "    oneDayData = auth2_client.intraday_time_series('activities/heart', base_date=oneDate, detail_level='1sec')\n",
    "    \n",
    "    date_list.append(oneDate)\n",
    "    \n",
    "    resting_list.append(oneDayData['activities-heart'][0]['value']['restingHeartRate'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fig, ax = plt.subplots(figsize=(10, 7))\n",
    "\n",
    "ax.plot(date_list, resting_list )\n",
    "\n",
    "# This is just making it so there isnt a grid line or text for every point\n",
    "xtick_list = []\n",
    "xticklabel_list = []\n",
    "for index, label in enumerate(ax.get_xticklabels()):\n",
    "    if index % 5 == 0:\n",
    "        xticklabel_list.append(label)\n",
    "        xtick_list.append(index)\n",
    "\n",
    "ax.grid(True,\n",
    "    axis = 'both',\n",
    "    zorder = 0,\n",
    "    linestyle = ':',\n",
    "    color = 'k')\n",
    "ax.tick_params(axis = 'both', labelsize = 20)\n",
    "ax.set_xticks(xtick_list)\n",
    "ax.tick_params(axis = 'x', rotation = 90,labelsize = 20)\n",
    "ax.set_xlim(0, index)\n",
    "#ax.set_xticklabels(ax.get_xticklabels(),rotation = 45, rotation_mode=\"anchor\", ha = 'right')\n",
    "ax.set_xlabel('Date', fontsize = 24)\n",
    "ax.set_ylabel('Resting Heart Rate', fontsize = 24)\n",
    "fig.tight_layout()\n",
    "fig.savefig('restingHR_graph.png', format = 'png', dpi = 300)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "resting_df = pd.DataFrame({'date': date_list, 'RHR': resting_list})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "resting_df.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 8.) Get Sleep Data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "startTime = pd.datetime(year = 2020, month = 1, day = 5)\n",
    "endTime = pd.datetime.today().date() - datetime.timedelta(days=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "allDates = pd.date_range(start=startTime, end = endTime)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "date_list = []\n",
    "df_list = []\n",
    "stages_df_list = []\n",
    "\n",
    "allDates = pd.date_range(start=startTime, end = endTime)\n",
    "\n",
    "for oneDate in allDates:\n",
    "    \n",
    "    oneDate = oneDate.date().strftime(\"%Y-%m-%d\")\n",
    "    \n",
    "    oneDayData = auth2_client.sleep(date=oneDate)\n",
    "    \n",
    "    # get number of minutes for each stage of sleep and such. \n",
    "    stages_df = pd.DataFrame(oneDayData['summary'])\n",
    "\n",
    "    df = pd.DataFrame(oneDayData['sleep'][0]['minuteData'])\n",
    "    \n",
    "    date_list.append(oneDate)\n",
    "    \n",
    "    df_list.append(df)\n",
    "    \n",
    "    stages_df_list.append(stages_df)\n",
    "    \n",
    "final_df_list = []\n",
    "\n",
    "final_stages_df_list = []\n",
    "\n",
    "for date, df, stages_df in zip(date_list, df_list, stages_df_list):\n",
    "\n",
    "    if len(df) == 0:\n",
    "        continue\n",
    "    \n",
    "    df.loc[:, 'date'] = pd.to_datetime(date)\n",
    "    \n",
    "    stages_df.loc[:, 'date'] = pd.to_datetime(date)\n",
    "    \n",
    "    final_df_list.append(df)\n",
    "    final_stages_df_list.append(stages_df)\n",
    "\n",
    "final_df = pd.concat(final_df_list, axis = 0)\n",
    "\n",
    "final_stages_df = pd.concat(final_stages_df_list, axis = 0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "columns = final_stages_df.columns[~final_stages_df.columns.isin(['date'])].values"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "columns"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pd.concat([final_stages_df[columns] + 2, final_stages_df[['date']]], axis = 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "# Export file to csv\n",
    "final_df.to_csv('minuteSleep' + '.csv', index = False)\n",
    "final_stages_df.to_csv('minutesStagesSleep' + '.csv', index = True)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
